iT邦幫忙

2022 iThome 鐵人賽

DAY 30
0
Mobile Development

使用 SwiftUI 讓有趣的點子變成 Apps系列 第 30

D30 - 忒修斯之船:替換船上的材料

  • 分享至 

  • xImage
  •  

忒修斯之船的題目是不斷的替換掉船上的材料,為了能顯示這個替換的過程,我打算用「顏色」的變化,來做材料替換的呈現。

規格:

  • 船的顏色要能變化,而且是漸漸變色,顏色設定為純色 A 到純色 B
  • 要有個 slider,在滑動的過程中,讓這條船的顏色變化。當船的變化從顏色 A 完全變成顏色 B,就視為所材料已被替換

船的 UI 變化規格:

如果希望在「一張圖」裡面,讓顏色進行變化,的確是可以做到,大概需要用到 mask 來處理。不過如果只是想要呈現顏色變化,我想實作的方式是,上下兩張圖疊起來。一開始上面的圖是不透明度 1,下面的圖不透明度是 0 。隨著材料被替換的過程,上面的圖不透明度往 0 開始靠近,下面的圖不透明度往1開始靠近。最後,上面的圖不透明度是 0,下面的圖不透明度是1。

/// 船
private var upShipImage: some View {
    Image(systemName: "ferry.fill")
      .renderingMode(.template)
      .foregroundColor(upShipColor)
      .font(.system(size: 200))
  }
  
  private var downShipImage: some View {
    Image(systemName: "ferry.fill")
      .renderingMode(.template)
      .foregroundColor(downShipColor)
      .font(.system(size: 200))
  }

整個 View 包含滑動的桿,程式碼如下

import SwiftUI

struct ShipView: View {
  
  private var upShipColor: Color {
    Color(white: 0, opacity: opacity)
  }
  
  @State private var opacity: Double = 1.0
  
  private var downShipColor: Color {
    Color(red: 1.0, green: 0, blue: 0, opacity: 1 - opacity)
  }
  
  private var progressString: String {
    "材料更換程度: \(percentageString) %"
  }
  
  private var percentageString: String {
    let opacityDouble = opacity * 100
    return String(format: "%.1f", opacityDouble)
  }
  
  var body: some View {
    
    VStack {
      
      Text("Ship of Theseus")
        .font(.largeTitle)
        .padding()
      
      Text(progressString)
        .font(.title2)
        .padding()
      
      ZStack {
        upShipImage
        downShipImage
      }
      
      Slider(
        value: $opacity,
        in: 0.0...1.0,
        step: 0.1
      )
        .padding()
    }
  }
  
  private var upShipImage: some View {
    Image(systemName: "ferry.fill")
      .renderingMode(.template)
      .foregroundColor(upShipColor)
      .font(.system(size: 200))
  }
  
  private var downShipImage: some View {
    Image(systemName: "ferry.fill")
      .renderingMode(.template)
      .foregroundColor(downShipColor)
      .font(.system(size: 200))
  }
  
}

struct ShipView_Previews: PreviewProvider {
  static var previews: some View {
    ShipView()
  }
}

來看一下 0% 和 100% 時的 UI

https://ithelp.ithome.com.tw/upload/images/20220930/20140622YtbE2kP42J.png

https://ithelp.ithome.com.tw/upload/images/20220930/201406228XDYAf7lPV.png

https://ithelp.ithome.com.tw/upload/images/20220930/20140622MWDe2KQQg6.png


上一篇
D29 - 忒修斯之船 UI
系列文
使用 SwiftUI 讓有趣的點子變成 Apps30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言